home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / tmodem23.arc / TM.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1985-05-19  |  19.0 KB  |  520 lines

  1. {$C-,V-,K-}
  2. (****************************************************************************)
  3. (*                                                                          *)
  4. (*   Author:   Paul Meiners                                                 *)
  5. (*             P & M  Software Company                                      *)
  6. (*             9350 Country Creek #30                                       *)
  7. (*             Houston, Texas 77036                                         *)
  8. (*                                                                          *)
  9. (*   Phone:    (713) 772-2090                                               *)
  10. (*                                                                          *)
  11. (*   Date:     March 3, 1985                                                *)
  12. (*                                                                          *)
  13. (*   Language: Turbo PASCAL version 3.00B                                   *)
  14. (*                                                                          *)
  15. (*   Remarks:  This program provides basic terminal emulation with capture  *)
  16. (*             to disk and XMODEM file transfer.  Uses interrupt driven     *)
  17. (*             serial I/O with circular queues.  Uses a removable window    *)
  18. (*             system.                                                      *)
  19. (*                                                                          *)
  20. (****************************************************************************)
  21.  
  22. program
  23.    TMODEM23;
  24.  
  25. type
  26.    strtype             = string[255];
  27.    string80            = string[80];
  28.    string40            = string[40];
  29.    string30            = string[30];
  30.    string10            = string[10];
  31.    alt_char_array      = array[ 96..127 ] of byte;
  32.  
  33. const
  34.    sin_buf_size        = 10240;
  35.    sin_buf_fill_lim    = 8192;
  36.    sin_buf_drain_lim   = 4096;
  37.    sout_buf_size       = 512;
  38.    capture_buf_size    = 1024;
  39.    max_xmodem_buffers  = 64;
  40.    max_dial_entries    = 16;
  41.    SOH                 = ^A;
  42.    CAN                 = ^X;
  43.    NAK                 = ^U;
  44.    ACK                 = ^F;
  45.    EOT                 = ^D;
  46.    CR                  = ^M;
  47.    LF                  = ^J;
  48.    CRLF                = ^M^J;
  49.    ESC                 = #27;
  50.    NUL                 = #00;
  51.    FF                  = ^L;
  52.    BS                  = ^H;
  53.    TAB                 = ^I;
  54.    default_stopbits    : integer = 1;
  55.    default_databits    : integer = 8;
  56.    default_parity      : integer = 0;       { 0=None, 1=Even, 2=Odd }
  57.    default_baud        : integer = 1200;
  58.    wait_increment      : integer = 333;     { 1/3 of a second.         }
  59.    datasegment         : integer = 0;
  60.    XON                 : integer = 17;      { XON  is a DC1 character. }
  61.    XOFF                : integer = 19;      { XOFF is a DC3 character. }
  62.    dial_pre_str        : string40 = 'ATDT ';
  63.    dial_post_str       : string10 = '|';          { | is replaced by CR }
  64.    modem_init_str      : string40 = 'AT S0=0|';
  65.    speaker_off         : string40 = 'AT M0|';
  66.    speaker_on          : string40 = 'AT M1|';
  67.    forced_carrier      : string10 = 'FALSE';
  68.    vt100_mode          : string10 = 'FALSE';
  69.    redial_time         : integer  = 60;
  70.    carrier_timeout     : integer  = 35;
  71.    alt_character       : alt_char_array = ( 4,97,98,99,100,101,102,241,104,105,
  72.                          217,191,218,192,197,196,196,196,196,196,195,180,193,
  73.                          194,179,243,242,227,216,156,250,127 );
  74.  
  75. type
  76.    sin_buffer_type     = array[1..sin_buf_size] of byte;
  77.    sout_buffer_type    = array[1..sout_buf_size] of byte;
  78.    func_buffer_type    = array[1..40] of string80;
  79.    capture_ptr_type    = ^capture_record;
  80.    capture_record      = record
  81.                             capture_store_ptr  : integer;
  82.                             capture_buffer     : array[1..capture_buf_size] of char;
  83.                             capture_next       : capture_ptr_type;
  84.                          end;
  85.    xmodem_buf          = array[1..128] of char;
  86.    xmodem_table        = array[1..max_xmodem_buffers] of xmodem_buf;
  87.    registerset         = record
  88.                             AX,BX,CX,DX,BP,DI,SE,DS,ES,Flags : integer;
  89.                          end;
  90.    dialrec             = record
  91.                             bbs_name            : string30;
  92.                             bbs_number          : string30;
  93.                             bbs_baud            : integer;
  94.                             bbs_parity          : integer;
  95.                             bbs_databits        : integer;
  96.                             bbs_stopbits        : integer;
  97.                          end;
  98.    dialarray           = record
  99.                             no_of_dial_entries  : integer;
  100.                             dir_entries         :
  101.                                 array[1..max_dial_entries] of dialrec;
  102.                          end;
  103.    sort_ptr_type       = ^dialsort;
  104.    dialsort            = record
  105.                             sort_rec            : dialrec;
  106.                             sort_next           : sort_ptr_type;
  107.                          end;
  108. var
  109.    rand                : real;
  110.    sin_buf_fill_cnt    : integer;
  111.    sin_xoff            : boolean;
  112.    sin_buffer_ptr      : ^sin_buffer_type;
  113.    sin_store_ptr       : integer;
  114.    sin_read_ptr        : integer;
  115.    sout_buffer_ptr     : ^sout_buffer_type;
  116.    sout_store_ptr      : integer;
  117.    sout_read_ptr       : integer;
  118.    sout_int_off        : boolean;
  119.    turn_IRQ_on         : byte;
  120.    turn_IRQ_off        : byte;
  121.    IRQ_vector_ofs      : integer;
  122.    IRQ_vector_seg      : integer;
  123.    hold_vector_ofs     : integer;
  124.    hold_vector_seg     : integer;
  125.    base_com_addr       : integer absolute $0000:$0400;
  126.    int_enable_reg      : integer;
  127.    int_ident_reg       : integer;
  128.    int_ident           : byte;
  129.    line_control_reg    : integer;
  130.    modem_control_reg   : integer;
  131.    line_status_reg     : integer;
  132.    line_status         : byte;
  133.    modem_status_reg    : integer;
  134.    sync_time           : integer;
  135.    xmodem_table_ptr    : ^xmodem_table;
  136.    xmodem_buf_cnt      : integer;
  137.    xmodem_ptr          : integer;
  138.    xmodem_rd           : integer;
  139.    continue_transfer   : boolean;
  140.    capture_flag        : boolean;
  141.    capture_warning     : boolean;
  142.    capture_first       : capture_ptr_type;
  143.    capture_curr        : capture_ptr_type;
  144.    printer_on          : boolean;
  145.    sort_curr           : sort_ptr_type;
  146.    sort_first          : sort_ptr_type;
  147.    sort_prev           : sort_ptr_type;
  148.    exit_program        : boolean;
  149.    func_key            : ^func_buffer_type;
  150.    keyfile             : text;
  151.    block_count         : integer;
  152.    error_count         : integer;
  153.    filename            : string80;
  154.    recv_file           : file;
  155.    xmit_file           : file;
  156.    textfile            : text;
  157.    textimage           : strtype;
  158.    dial_drive          : integer;
  159.    dial_PATH           : string80;
  160.    cnf_PATH            : string80;
  161.    dialfile            : file of dialarray;
  162.    dial_dir            : dialarray;
  163.    dialarray_number    : integer;
  164.    dial_str            : string40;
  165.    redial_number       : string40;
  166.    redial_name         : string30;
  167.    baud                : integer;
  168.    stopbits            : integer;
  169.    databits            : integer;
  170.    par                 : integer;
  171.    kbd_char            : char;
  172.    a_key               : string[2];
  173.    regs                : registerset;
  174.    half_duplex         : boolean;
  175.    ascii_mode          : boolean;
  176.    escape_mode         : boolean;
  177.    escape_number       : byte;
  178.    escape_register     : array[1..50] of byte;
  179.    escape_str          : strtype;
  180.    escape_type         : char;
  181.    line_drawing_chars  : boolean;
  182.    ok                  : boolean;
  183.    parity_ch           : string10;
  184.    baud_ch             : string10;
  185.    stop_ch             : string10;
  186.    data_ch             : string10;
  187.    FGcolor,BGcolor     : integer;
  188.    FG,BG               : integer;
  189.    white_shade         : integer;
  190.    scale               : array[ 0..20 ] of real;
  191.    notes               : array[ 1..84 ] of integer;
  192.    factor              : array[ 0..6 ] of real;
  193.    tempo               : real;
  194.    note_length         : integer;
  195.    octave              : integer;
  196.    dots                : integer;
  197.    dnote               : array[ 0..6 ] of real;
  198.    music_mode          : real;
  199.    rest_mode           : real;
  200.    silent_mode         : boolean;
  201.    monitor_mode        : boolean;
  202.    tune_number         : integer;
  203.    time_fix            : string10;
  204.    curr_time           : string10;
  205.    start_time          : string10;
  206.    dial_time           : string10;
  207.    a_second            : integer;
  208.    yes_no              : string[4];
  209.  
  210. {$I BASIC.INC}
  211. {$I RWINDOW.INC}
  212. (****************************************************************************)
  213. (*                          COMMAND DISTRIBUTOR                             *)
  214. (****************************************************************************)
  215.    procedure
  216.       exec_command(ch : char); FORWARD;
  217.  
  218. (****************************************************************************)
  219. (*                              WAIT FOR A KEY                              *)
  220. (****************************************************************************)
  221.    procedure
  222.       wait_for_key;
  223.    begin
  224.       write(' Press ANY key to continue...');
  225.       repeat
  226.          repeat
  227.             a_key := inkey;
  228.          until a_key <> '';
  229.          if length(a_key) = 2 then begin
  230.             exec_command(a_key[2]);
  231.             a_key := '';
  232.          end;
  233.       until length(a_key) = 1;
  234.    end;
  235.  
  236. (****************************************************************************)
  237. (*                           REWRITE CONFIG FILE                            *)
  238. (****************************************************************************)
  239.    procedure
  240.       rewrite_config_file;
  241.    begin
  242.       rewrite(textfile);
  243.       writeln(textfile,'ST=',default_stopbits);
  244.       writeln(textfile,'DA=',default_databits);
  245.       writeln(textfile,'PA=',default_parity);
  246.       writeln(textfile,'BA=',default_baud);
  247.       writeln(textfile,'WA=',wait_increment);
  248.       writeln(textfile,'PR=',dial_pre_str);
  249.       writeln(textfile,'PO=',dial_post_str);
  250.       writeln(textfile,'MI=',modem_init_str);
  251.       writeln(textfile,'SY=',speaker_on);
  252.       writeln(textfile,'SN=',speaker_off);
  253.       writeln(textfile,'RT=',redial_time);
  254.       writeln(textfile,'FC=',forced_carrier);
  255.       writeln(textfile,'CT=',carrier_timeout);
  256.       writeln(textfile,'DP=',dial_PATH);
  257.       writeln(textfile,'XO=',XON);
  258.       writeln(textfile,'XF=',XOFF);
  259.       writeln(textfile,'VT=',vt100_mode);
  260.       a_second := round( 3.003004 * wait_increment );
  261.    end;
  262.  
  263. {$I MUSIC.INC}
  264. {$I DIRECT.INC}
  265. {$I TM1.INC}
  266. (****************************************************************************)
  267. (*                              SEND STRING                                 *)
  268. (****************************************************************************)
  269.    procedure
  270.       send_str( s : strtype );
  271.    var
  272.       i  : integer;
  273.    begin
  274.       for i:=1 to length( s ) do
  275.          store_sout_buffer( s[i] );
  276.    end;
  277. {$I TM2.INC}
  278. (****************************************************************************)
  279. (*                            KEYBOARD HANDLER                              *)
  280. (****************************************************************************)
  281.    procedure
  282.       keyboard;
  283.    begin
  284.       if length(a_key) = 1 then begin
  285.          if half_duplex then scrwrite(a_key[1]);
  286.          store_sout_buffer(a_key[1]);
  287.       end
  288.       else
  289.          exec_command(a_key[2]);
  290.    end;
  291.  
  292. (****************************************************************************)
  293. (*                           TERMINAL PROCESSOR                             *)
  294. (****************************************************************************)
  295.    procedure
  296.       terminal_processor;
  297.    begin
  298.       if sin_store_ptr <> sin_read_ptr then begin
  299.             kbd_char := read_sin_buffer;
  300.             scrwrite(kbd_char);
  301.       end;
  302.       a_key := inkey;
  303.       if a_key <> '' then keyboard;
  304.    end;
  305.  
  306. (****************************************************************************)
  307. (*                       INITIALIZE FUNCTION KEYS                           *)
  308. (****************************************************************************)
  309.    procedure
  310.       initialize_function_keys;
  311.    var
  312.       i   : byte;
  313.    begin
  314.       for i:=1 to 40 do func_key^[i]:='';
  315.       assign(keyfile,'TMODEM.KEY');
  316.       {$I-}
  317.       reset(keyfile);
  318.       {$I+}
  319.       ok:=(ioresult = 0);
  320.       if not ok then begin
  321.          rewrite(keyfile);
  322.          for i:=1 to 40 do
  323.             writeln(keyfile,func_key^[i]);
  324.       end
  325.       else begin
  326.          i :=0;
  327.          while ( not eof(keyfile) ) and ( i < 40 ) do begin
  328.             i := i + 1;
  329.             readln(keyfile,func_key^[i]);
  330.          end;
  331.       end;
  332.       close(keyfile);
  333.    end;
  334.  
  335. (****************************************************************************)
  336. (*                             READ CONFIG FILE                             *)
  337. (****************************************************************************)
  338.    procedure
  339.       read_config_file;
  340.    var
  341.       teststr  : string[2];
  342.       dataval  : integer;
  343.    begin
  344.       assign(textfile,'TMODEM.CNF');
  345.       {$I-}
  346.       reset(textfile);
  347.       {$I+}
  348.       ok:=(ioresult = 0);
  349.       if not ok then
  350.          rewrite_config_file
  351.       else begin
  352.          while not eof(textfile) do begin
  353.             readln(textfile,textimage);
  354.             teststr := copy(textimage+'  ',1,2);
  355.             upstring(teststr);
  356.             dataval := bval(copy(textimage+'          ',4,9));
  357.             delete(textimage,1,3);
  358.             if teststr = 'ST' then default_stopbits := dataval;
  359.             if teststr = 'DA' then default_databits := dataval;
  360.             if teststr = 'PA' then default_parity := dataval;
  361.             if teststr = 'BA' then default_baud := dataval;
  362.             if teststr = 'WA' then wait_increment := dataval;
  363.             if teststr = 'PR' then dial_pre_str := textimage;
  364.             if teststr = 'MI' then modem_init_str := textimage;
  365.             if teststr = 'PO' then dial_post_str := textimage;
  366.             if teststr = 'SN' then speaker_off := textimage;
  367.             if teststr = 'SY' then speaker_on := textimage;
  368.             if teststr = 'RT' then redial_time := dataval;
  369.             if teststr = 'FC' then forced_carrier := textimage;
  370.             if teststr = 'CT' then carrier_timeout := dataval;
  371.             if teststr = 'DP' then dial_PATH := textimage;
  372.             if teststr = 'VT' then vt100_mode := textimage;
  373.          end;
  374.       end;
  375.       close(textfile);
  376.       a_second := round( 3.003004 * wait_increment );
  377.       if vt100_mode = 'T' then silent_mode:=true;
  378.    end;
  379.  
  380. (****************************************************************************)
  381. (*                           MAIN  LINE  CODE                               *)
  382. (****************************************************************************)
  383. begin
  384.    randomize;
  385.    FGcolor := white;
  386.    BGcolor := black;
  387.    FG := FGcolor;
  388.    BG := BGcolor;
  389.    white_shade := lightgray;
  390.    lowvideo;
  391.    textcolor( FG );
  392.    textbackground( BG );
  393.    window(1,1,80,25);
  394.    clrscr;
  395.    initwin;
  396.    capture_flag := false;
  397.    printer_on := false;
  398.    ascii_mode := false;
  399.    escape_mode := false;
  400.    silent_mode := true;
  401.    monitor_mode := false;
  402.    line_drawing_chars := false;
  403.    time_fix := time;
  404.    dial_time := time_fix;
  405.  
  406.    if base_com_addr = $3F8 then   { Setup vectors and port addresses. }
  407.       begin
  408.          turn_IRQ_on := $EF;
  409.          turn_IRQ_off := $10;
  410.          IRQ_vector_ofs := $0030;
  411.          IRQ_vector_seg := $0032;
  412.       end
  413.    else
  414.       begin
  415.          turn_IRQ_on := $F7;
  416.          turn_IRQ_off := $08;
  417.          IRQ_vector_ofs := $002C;
  418.          IRQ_vector_seg := $002E;
  419.       end;
  420.  
  421.    new( sin_buffer_ptr );
  422.    new( sout_buffer_ptr );
  423.    new( xmodem_table_ptr );
  424.    new( func_key );
  425.    sin_store_ptr := 1;
  426.    sin_read_ptr := 1;
  427.    sin_buf_fill_cnt := 0;
  428.    sin_xoff := false;
  429.    sout_store_ptr := 1;
  430.    sout_read_ptr := 1;
  431.    hold_vector_ofs := memw[$0000:IRQ_vector_ofs];
  432.    hold_vector_seg := memw[$0000:IRQ_vector_seg];
  433.    memw[$0000:IRQ_vector_ofs] := ofs(async_intr_handler);
  434.    memw[$0000:IRQ_vector_seg] := CSeg;
  435.    datasegment := DSeg;
  436.    int_enable_reg := base_com_addr + 1;
  437.    int_ident_reg := base_com_addr + 2;
  438.    line_control_reg := base_com_addr + 3;
  439.    modem_control_reg := base_com_addr + 4;
  440.    line_status_reg := base_com_addr + 5;
  441.    modem_status_reg := base_com_addr + 6;
  442.  
  443.    dial_drive := ord(default_drive) - ord('A') + 1;
  444.    getdir(dial_drive,dial_PATH);
  445.    if dial_PATH[length(dial_PATH)] <> '\' then
  446.       dial_PATH := dial_PATH + '\';
  447.    cnf_PATH := dial_PATH;
  448.    read_config_file;
  449.  
  450.    baud := default_baud;                     { Initialize the serial port. }
  451.    stopbits := default_stopbits;
  452.    databits := default_databits;
  453.    par := default_parity;
  454.    setserial(baud,stopbits,databits,par);
  455.    exit_program := false;
  456.    half_duplex := false;
  457.  
  458.    dial_str := modem_init_str;
  459.    dialer;
  460.    redial_number := '';
  461.    redial_name := '';
  462.    initialize_function_keys;
  463.  
  464.    mkwin(2,2,79,22,'TMODEM, ver 2.3');
  465.    writeln;
  466.    writeln(' If you use this program and like it, a contribution ($20 suggested) will');
  467.    writeln(' be appreciated.');
  468.    writeln;
  469.    writeln;
  470.    writeln('                          P & M  Software Co.');
  471.    writeln('                          9350 Country Creek #30');
  472.    writeln('                          Houston, Texas 77036');
  473.    writeln;
  474.    writeln;
  475.    writeln(' You are encouraged to copy and share this program with others, on the');
  476.    writeln(' condition that the program not be sold for profit, except by the author,');
  477.    writeln(' and that this notice is not altered, bypassed, or removed.');
  478.    writeln;
  479.    writeln('                                                      Good Luck,');
  480.    writeln('                                     The Author --->  Paul Meiners.');
  481.    writeln;
  482.    escape_win;
  483.    gotoxy(19,23);
  484.    write('Copyright (c) 1985 by: P & M  Software Co.');
  485.    reset_win;
  486.  
  487.    write(' Do You Want Music? ');
  488.    repeat
  489.       rand := random;
  490.    until keypressed;
  491.    read(kbd,kbd_char);
  492.    write(kbd_char);
  493.    initialize_music;
  494.    if upcase( kbd_char ) = 'Y' then
  495.       silent_mode := false;
  496.    rmwin;
  497.    sin_store_ptr := sin_read_ptr;
  498.    display_prompts;
  499.  
  500.    delay( wait_increment );
  501.    repeat
  502.       terminal_processor;
  503.    until exit_program;
  504.  
  505.    port[int_enable_reg] := 0;                  { Turn off modem and reset }
  506.    port[modem_control_reg] := 0;               { vectors.                 }
  507.    port[$21] := port[$21] or turn_IRQ_off;
  508.    memw[$0000:IRQ_vector_ofs] := hold_vector_ofs;
  509.    memw[$0000:IRQ_vector_seg] := hold_vector_seg;
  510.    dispose( func_key );
  511.    dispose( xmodem_table_ptr );
  512.    dispose( sout_buffer_ptr );
  513.    dispose( sin_buffer_ptr );
  514.  
  515.    if capture_flag then toggle_capture_mode;
  516.    window(1,1,80,25);
  517.    gotoxy(1,25);
  518.    clreol;
  519.    write('End of Program.');
  520. end.